package com.jwong.common.web.exception;

import com.jwong.common.entity.vo.Result;
import com.jwong.common.exception.BaseErrorCode;
import com.jwong.common.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.core.AuthenticationException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.MultipartException;

@Slf4j
@RestControllerAdvice(basePackages = {
        "com.jwong.client.rest"

})
public class DefaultExceptionHandlerAdvice {

    @ExceptionHandler(value = {BaseException.class})
    public Result<Void> baseException(BaseException ex) {
        log.error("base exception:{}", ex.getMessage());
        return Result.fail(ex.getErrorCode());
    }

    @ExceptionHandler(value = {AccessDeniedException.class})
    @ResponseStatus(HttpStatus.FORBIDDEN)
    public Result<Void> forbiddenException(AccessDeniedException ex) {
        log.error("access denied exception:{}", ex.getMessage());
        return Result.fail(BaseErrorCode.SC_FORBIDDEN);
    }

    @ExceptionHandler(value = {MethodArgumentNotValidException.class})
    public Result<Void> serviceException(MethodArgumentNotValidException ex) {
        log.error("service exception:{}", ex.getMessage());
        return Result.fail(BaseErrorCode.ARGUMENT_NOT_VALID);
    }

    @ExceptionHandler(value = {MissingServletRequestParameterException.class})
    public Result<Void> missingServletRequestParameterException(MissingServletRequestParameterException ex) {
        log.error("missing servlet request parameter exception:{}", ex.getMessage());
        return Result.fail(BaseErrorCode.ARGUMENT_NOT_VALID);
    }

    @ExceptionHandler(value = {MultipartException.class})
    public Result<Void> uploadFileLimitException(MultipartException ex) {
        log.error("upload file size limit:{}", ex.getMessage());
        return Result.fail(BaseErrorCode.UPLOAD_FILE_SIZE_LIMIT);
    }

    @ExceptionHandler(value = {AuthenticationException.class})
    public Result<Void> authenticationException(AuthenticationException ex) {
        log.error("AuthenticationException error:{}", ex.getMessage());
        return Result.fail(ex.getMessage());
    }

    @ExceptionHandler(value = {Exception.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<Void> exception(Exception ex) {
        log.error("Internal Server Error:{}", ex.getMessage());
        return Result.fail();
    }

    @ExceptionHandler(value = {Throwable.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Result<Void> throwable(Throwable t) {
        log.error("Internal Server Error:{}", t.getMessage());
        return Result.fail();
    }

}